/*=====================================================================

  File:      Application.cs
  Summary:   SQL Remote Blob Storage sample application.
             Sample application used to demonstrate usage of the Remote 
             Blob Storage libraries.
  Date:	     July 21st, 2008

---------------------------------------------------------------------

  This file is part of the Microsoft SQL Server Code Samples.
  Copyright (C) Microsoft Corporation.  All rights reserved.

This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

======================================================= */

using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Transactions;

namespace Microsoft.Samples.RemoteBlobStorage
{
    /// <summary>
    /// Sample Remote Blob Storage Application.
    /// </summary>
    public
    sealed
    class Application
    {
        private Application() { }

        static int Main(string[] args)
        {
            Console.WriteLine("Running Remote Blob Storage Sample Application");
            try
            {
                // Load the connection string to user from the Application.exe.config file.
                //
                ConnectionStringSettingsCollection connstrings = ConfigurationManager.ConnectionStrings;
                if (connstrings == null || connstrings["application"] == null)
                {
                    throw new ArgumentException("A valid connection string must be specified in the Application.exe.config file.");
                }
                s_Connection = connstrings["application"].ConnectionString;

                // Initialize the database connection, create a test table in the default catalog.
                //
                InitializeDatabase();

                // Basic store blob. Uses the default store and default collection.
                //
                StoreSimple.RunStoreSimple(s_Connection);

                // Custom store blob. Creates a new collection and creates the new blob in that collection.
                //
                StoreCustom.RunStoreCustom(s_Connection);

                // Stores a blob using the stream pull methods.
                //
                StoreStreamPull.RunStoreStreamPull(s_Connection);

                // Stores a blob using the stream push methods.
                //
                StoreStreamPush.RunStoreStreamPush(s_Connection);

                // Reads all blob data from the application's tables.
                //
                FetchSimple.RunFetchSimple(s_Connection);

                // Reads blob data using the stream pull methods.
                //
                FetchStreamPull.RunFetchStreamPull(s_Connection);

                // Reads blob data using the stream push methods.
                //
                FetchStreamPush.RunFetchStreamPush(s_Connection);

                // Reads blob data asynchronously.
                //
                FetchAsync.RunFetchAsync(s_Connection);

                // Success
                //
                return 0;
            }
            catch (Exception ex)
            {
                // Top level exception handler.
                //
                Console.WriteLine("An error occurred when running the Application sample.");
                Console.WriteLine(ex.ToString());
                return 1;
            }
        }

        /// <summary>
        /// Initialize and verify the connection. Create a test table in the selected catalog if necessary.
        /// </summary>
        private
        static void InitializeDatabase()
        {
            // Create a new transaction. Remote Blob Storage applications should use the TransactionScope classes 
            // to create and manage transaction lifetimes. The TransactionScopeOption allows fine control of
            // the transactions that will be passed to SQL operations.
            //
            using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
            {
                using (SqlConnection conn = new SqlConnection(s_Connection))
                {
                    conn.Open();

                    string createTestTable = @" 
                            -- Unregister and drop the table if it exists
                            if exists (select * from sys.tables where name = 'ApplicationSampleTable') 
                            begin
                                -- Unregister the column before dropping the table. If this is not done, 
                                -- a 'referenced by object' error will occur.
                                execute mssqlrbs.rbs_sp_unregister_column dbo, ApplicationSampleTable, BlobId
                                drop table ApplicationSampleTable
                            end

                            -- Create the table. Use varbinary(64) type for the BlobId column. Other columns
                            -- are for the Application's metadata and are not used by RBS.
                            create table ApplicationSampleTable (
                                id uniqueidentifier default newid(),
                                SearchTags varchar(max),
                                BlobId varbinary(64)
                            )

                            -- Create a nonclustered index on the BlobId column. This is optional and allows 
                            -- fast lookups of BlobId references by the GC.
                            create index ApplicationSampleTable_ix_BlobId on ApplicationSampleTable (BlobId)

                            -- Register the newly created column with RBS. This allows the GC to correctly 
                            -- function.
                            execute mssqlrbs.rbs_sp_register_column dbo, ApplicationSampleTable, BlobId
                            ";

                    using (SqlCommand cmd = new SqlCommand(createTestTable, conn))
                    {
                        cmd.ExecuteNonQuery();
                    }
                    Console.WriteLine("Successfully created Application test tables.");
                }
                // Commit the transaction. This will only hit if there were no exceptions.
                //
                ts.Complete();
            }
        }

        private static string s_Connection;
    }
}
